/**
 * ===================================
 * 玩家游戏对象 (Player.js)
 * ===================================
 * 
 * 功能说明：
 * - 管理玩家飞船的所有行为（移动、射击、动画等）
 * - 继承自Physics.Arcade.Image，具备物理属性
 * - 使用状态机管理玩家的不同状态
 * - 实现对象池管理子弹，优化性能
 * 
 * 状态说明：
 * - waiting: 等待状态（游戏开始前）
 * - start: 启动状态（播放入场动画）
 * - can_move: 可移动状态（正常游戏状态）
 * 
 * 作者：游戏开发团队
 * 创建时间：2024年
 */

// 导入Phaser3核心模块
import { GameObjects, Physics } from "phaser";
// 导入子弹类
import { Bullet } from "./Bullet";

/**
 * 玩家类 - 继承自Physics.Arcade.Image
 * 具备物理属性的图像对象，可以参与碰撞检测和物理运算
 */
export class Player extends Physics.Arcade.Image {
    
    // ===== 玩家状态管理 =====
    state = "waiting";              // 当前状态：waiting(等待) | start(启动) | can_move(可移动)
    
    // ===== 视觉效果对象 =====
    propulsion_fire = null;         // 推进器火焰精灵对象
    
    // ===== 场景引用 =====
    scene = null;                   // 当前场景的引用，用于访问场景方法和属性
    
    // ===== 子弹管理 =====
    bullets = null;                 // 子弹对象池，用于管理玩家发射的所有子弹

    /**
     * 构造函数 - 初始化玩家对象
     * @param {Object} config - 配置对象
     * @param {Phaser.Scene} config.scene - 当前场景实例
     */
    constructor({scene}) {
        // 调用父类构造函数，创建物理图像对象
        // 参数：场景, X坐标(-190,屏幕外), Y坐标(100), 纹理ID("player")
        super(scene, -190, 100, "player");
        
        // 保存场景引用
        this.scene = scene;
        
        // 将玩家对象添加到场景的显示列表中
        this.scene.add.existing(this);
        
        // 将玩家对象添加到场景的物理世界中，启用物理属性
        this.scene.physics.add.existing(this);

        // ===== 创建推进器火焰效果 =====
        // 在玩家飞船后方创建火焰精灵
        this.propulsion_fire = this.scene.add.sprite(
            this.x - 32,                // X坐标：玩家位置向左偏移32像素
            this.y,                     // Y坐标：与玩家相同
            "propulsion-fire"           // 使用推进器火焰纹理
        );
        // 播放火焰动画
        this.propulsion_fire.play("fire");

        // ===== 创建子弹对象池 =====
        // 使用对象池技术管理子弹，避免频繁创建和销毁对象，提升性能
        this.bullets = this.scene.physics.add.group({
            classType: Bullet,          // 对象池中对象的类型
            maxSize: 100,              // 对象池最大容量（最多100颗子弹）
            runChildUpdate: true       // 自动调用池中每个对象的update方法
        });
    }

    /**
     * ===== 开始游戏方法 =====
     * 播放玩家入场动画，从屏幕左侧飞入游戏区域
     */
    start() {
        // 切换到启动状态
        this.state = "start";
        
        // 用于存储拖尾火焰效果的数组
        const propulsion_fires_trail = [];

        // ===== 创建入场动画 =====
        // 使用Tween动画让玩家从左侧飞入
        this.scene.tweens.add({
            targets: this,              // 动画目标：玩家对象
            x: 200,                    // 目标X坐标：200像素
            duration: 800,             // 动画持续时间：800毫秒
            delay: 1000,               // 延迟时间：1秒后开始
            ease: "Power2",            // 缓动函数：二次方缓动
            yoyo: false,               // 不使用往返动画
            
            // ===== 动画更新回调 =====
            // 在动画过程中每帧调用，创建拖尾效果
            onUpdate: () => {
                // 在玩家当前位置创建火焰精灵
                const propulsion = this.scene.add.sprite(
                    this.x - 32,       // 火焰位置：玩家后方
                    this.y,            // 与玩家同一高度
                    "propulsion-fire"  // 使用火焰纹理
                );
                propulsion.play("fire");  // 播放火焰动画
                propulsion_fires_trail.push(propulsion);  // 添加到拖尾数组
            },
            
            // ===== 动画完成回调 =====
            // 入场动画结束后的处理
            onComplete: () => {
                // ===== 清理拖尾效果 =====
                // 逐个淡出并销毁拖尾火焰
                propulsion_fires_trail.forEach((propulsion, i) => {
                    this.scene.tweens.add({
                        targets: propulsion,        // 目标：拖尾火焰精灵
                        alpha: 0,                  // 透明度：完全透明
                        scale: 0.5,                // 缩放：缩小到50%
                        duration: 200 + (i * 2),  // 持续时间：错开淡出时间
                        ease: "Power2",            // 缓动函数
                        onComplete: () => {
                            propulsion.destroy();  // 动画完成后销毁对象
                        }
                    });
                });

                // ===== 更新主推进器位置 =====
                this.propulsion_fire.setPosition(this.x - 32, this.y);

                // ===== 切换到可移动状态 =====
                // 入场动画完成，玩家现在可以接受控制
                this.state = "can_move";
            }
        });
    }

    /**
     * ===== 玩家移动方法 =====
     * 处理玩家的上下移动，包含边界检测
     * @param {string} direction - 移动方向："up" 或 "down"
     */
    move(direction) {
        // 只有在可移动状态下才能移动
        if(this.state === "can_move") {
            if (direction === "up" && this.y - 10 > 0) {
                // 向上移动：检查不超出屏幕上边界
                this.y -= 5;                    // 每次移动5像素
                this.updatePropulsionFire();    // 更新推进器位置
            } else if (direction === "down" && this.y + 75 < this.scene.scale.height) {
                // 向下移动：检查不超出屏幕下边界（考虑飞船高度75像素）
                this.y += 5;                    // 每次移动5像素
                this.updatePropulsionFire();    // 更新推进器位置
            }
        }
    }

    /**
     * ===== 射击方法 =====
     * 发射子弹，支持指定目标位置（鼠标点击）或默认直线射击
     * @param {number} x - 目标X坐标（可选）
     * @param {number} y - 目标Y坐标（可选）
     */
    fire(x, y) {
        // 只有在可移动状态下才能射击
        if (this.state === "can_move") {
            // ===== 从对象池获取子弹 =====
            const bullet = this.bullets.get();
            
            if (bullet) {
                // 发射子弹：从玩家前方发出
                bullet.fire(
                    this.x + 16,    // 子弹起始X：玩家位置向右偏移16像素
                    this.y + 5,     // 子弹起始Y：玩家位置向下偏移5像素
                    x,              // 目标X坐标（可选）
                    y               // 目标Y坐标（可选）
                );
            }
        }
    }

    /**
     * ===== 更新推进器火焰位置 =====
     * 当玩家移动时，同步更新推进器火焰的位置
     */
    updatePropulsionFire() {
        this.propulsion_fire.setPosition(
            this.x - 32,    // X坐标：玩家后方32像素
            this.y          // Y坐标：与玩家相同
        );
    }

    /**
     * ===== 更新方法 =====
     * 每帧调用，处理玩家的持续行为
     * 由场景的update()方法调用，或对象池自动调用
     */
    update() {
        // ===== 微妙的悬浮效果 =====
        // 使用正弦函数创建轻微的上下浮动，增加视觉动感
        // Math.sin(this.scene.time.now / 200)：基于游戏时间的正弦波
        // * 0.10：振幅很小，只有0.1像素的浮动
        this.y += Math.sin(this.scene.time.now / 200) * 0.10;
        
        // ===== 同步推进器火焰位置 =====
        // 确保推进器火焰始终跟随玩家的Y坐标变化
        this.propulsion_fire.y = this.y;
    }

}